/**
 * @file    woshcesrv.cpp
 * @brief   WOSH Server for Windows CE/Mobile 6.1
 *
 *          Refer to \ref page_applications_woshcesrv for more information.
 *
 *
 ****************************************************************************
 * \section page_applications_woshcesrv WOSH CE Server [WindowsCE / Mobile]
 *
 * This application is a tiny server with minimal interface, designed to
 * host wosh::devices:WindowsMobileBundlle and allow interaction with
 * other hosts (WOSH servers) on the network. Because of that,
 * unlike standard WOSH Server, this application doesn't support
 * dynamic loading (allocators) of Bundle, NetworkProtocol and Database.
 *
 *
 * \image html extras/screenshots/WOSH.wincesrv.1.png "WOSH CE Server:Network Menu"
 * \image html extras/screenshots/WOSH.wincesrv.2.png "WOSH CE Server:WindowsMobileBundle Menu"
 *
 *
 * Software is intent to be active 24/7 on device connected (RNDIS)
 * to the Home LAN and reachable by another WOSH Server.
 * Main goal is to provide to the distributed system some communication
 * (such as messaging) features.
 *
 * As any application, woshcesrv may lose the active focus, you may  display
 * the GUI again using the Task Manager (it may be usually shown hitting
 * power button once).
 *
 * Tested with Microsoft Visual Studio 2008, Windows Mobile 6 SDK, QT 4.5 for WinCE
 *
 *
 *
 * Microsoft Visual Studio 2008 - \b C++ Command line dump:
 * \verbatim
/Os /I "g:\dev\Qt\wince.4.5.0\include\QtCore" /I "g:\dev\Qt\wince.4.5.0\include\QtNetwork" /I "g:\dev\Qt\wince.4.5.0\include\QtXml" /I "g:\dev\Qt\wince.4.5.0\include" /I "." /I "..\tmp\moc" /I "g:\dev\Qt\wince.4.5.0\include\ActiveQt" /I "..\tmp\ui" /I "g:\dev\Qt\wince.4.5.0\mkspecs\default" /D "DEBUG" /D "_DEBUG" /D "_WINDOWS" /D "UNDER_CE" /D "WINCE" /D "_UNICODE" /D "UNICODE" /D "_WIN32" /D "QT_NO_PRINTER" /D "QT_NO_PRINTDIALOG" /D "SMARTPHONE2003_UI_MODEL" /D "ARMV4I" /D "_ARMV4I_" /D "armv4i" /D "_ARM_" /D "ARM" /D "_M_ARM" /D "__arm__" /D "Q_OS_WINCE_WM" /D "QT_KEYPAD_NAVIGATION" /D "_WIN32_WCE=0x502" /D "QT_NO_CURSOR" /D "_OS_WIN32" /D "_OS_WINCE" /D "WOSH_CORE" /D "WOSH_CORE_UTILS" /D "WOSH_AUTOMATIONS" /D "WOSH_BUILDING" /D "WOSH_COMMUNICATION" /D "WOSH_DATABASE_XML" /D "WOSH_ENTERTAINMENT" /D "WOSH_NETWORK" /D "WOSH_PLUGINS" /D "WOSH_SECURITY" /D "WOSH_BUNDLE_Discovery" /D "WOSH_BUNDLE_WindowsMobile" /D "QT_THREAD_SUPPORT" /D "QT_DLL" /D "QT_XML_LIB" /D "QT_NETWORK_LIB" /D "QT_CORE_LIB" /FD /EHsc /MDd /GS- /fp:fast /Zc:wchar_t- /GR /Fo"..\tmp\\" /Fd".\\" /W3 /nologo /c /Zi /TP
\endverbatim
 *
 * Microsoft Visual Studio 2008 - \b Linker Command line dump:
 * \verbatim
/OUT:"..\bin\woshcesrv.exe" /NOLOGO /LIBPATH:"g:\dev\Qt\wince.4.5.0\lib" /MANIFEST:NO /NODEFAULTLIB:"OLDNAMES.LIB" /DEBUG /DYNAMICBASE /NXCOMPAT /ERRORREPORT:PROMPT corelibc.lib g:\dev\Qt\wince.4.5.0\lib\qtmaind.lib cellcore.lib sms.lib cemapi.lib aygshell.lib g:\dev\Qt\wince.4.5.0\lib\QtXmld4.lib g:\dev\Qt\wince.4.5.0\lib\QtNetworkd4.lib g:\dev\Qt\wince.4.5.0\lib\QtCored4.lib  coredll.lib corelibc.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib
\endverbatim
 *
 *
 *
 * \par How to configure RNDIS
 *  - Plug device
 *  - ensure module has been loaded (execute 'dmesg')
 *  - ensure network interface has been crated (execute 'ifconfig -a')
 *  - assign IP to device (execute 'dhclient3 rndis0')
 *  - ping device (execute 'ping 169.254.2.1')
 *
 *  Device is now part of the network.
 *  You may need to setup routing for accessing the network/internet
 *
 * \verbatim
alex@linbox:/$ sudo echo "1" > /proc/sys/net/ipv4/ip_forward
\endverbatim
 *
 *
 *
 ****************************************************************************
 * @version $Id: woshcesrv.cpp 2539 2010-05-25 21:37:57Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/

//////////////////////////////////////////////////////////////////
#define _CONFIG_FILE		"wosh.ce.conf"
#define _LOG_FILE			"wosh.log"
//////////////////////////////////////////////////////////////////

#include <core/WoshKernel.h>
#include <core/LogContext.h>
#include <core/LogHandlers.h>
#include <core/FileSystem.h>
#include <core/BundleManager.h>

#include <framework/network/NetworkProtocolTcp.h>

#include <bundles/services/DiscoveryUdp/DiscoveryUdpBundle.h>
#include <bundles/devices/WindowsMobile/WindowsMobileBundle.h>

#include <QCoreApplication>

//////////////////////////////////////////////////////////////////

#define INITGUID ///@todo check if 'INITGUID' is required!??
#include <windows.h>
#include "wincesrv_form.h"

//////////////////////////////////////////////////////////////////
HINSTANCE g_hInst;	///< Local copy of hInstance
//////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////
using namespace std;
using namespace wosh;
//////////////////////////////////////////////////////////////////


/**
 * @brief   Entry point for the application.
 * @param [in] hInstance Handle to the current instance of the application.
 * @param [in] hPrevInstance Handle to the previous instance of the application. (always NULL)
 * @param [in] lpCmdLine Pointer to a null-terminated string specifying the command line for the application, excluding the program name
 * @param [in] nShowCmd Specifies how the window is to be shown.
 * @warning You may need to clear Value of Project->Properties->Linker->Advanced->Entry Point
 */
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nShowCmd )
{
	//////////////////////////////////////////////////////////////////////////////////////
	// Check if - is running. If it's running then focus on the window
	HWND hMenuWnd = FindWindow( TEXT("Dialog"), (LPCTSTR)LoadString(hInstance, IDS_MENU_TITLE, NULL, 0));
    if ( hMenuWnd != NULL ) {
		SetForegroundWindow(hMenuWnd);    
		return 0;
	}

	//////////////////////////////////////////////////////////////////////////////////////
	// store the hInstance and init the application
	g_hInst = hInstance;
	int noparam = 0;
    QCoreApplication app(noparam, NULL);
	std::string strAppDirectory = FileSystem::getCurrentWorkingDirectory() + _FileSystem_PathSeparatorLocal;

	//////////////////////////////////////////////////////////////////////////////////////
	// alloc Log
	DefaultSharedLogHandler::getInstance()->setFileName( strAppDirectory + _LOG_FILE );
	DefaultSharedLogHandler::getInstance()->setStdOut(false, false);

	//////////////////////////////////////////////////////////////////////////////////////
	// load settings [required: kernelname, discovery addresses, TCP binding]
	Settings* woshSettings = new Settings();
	WRESULT loaded = woshSettings->loadConfigurationFile( strAppDirectory +  _CONFIG_FILE );
	if ( loaded != WRET_OK ) {
		if ( loaded == WRET_ERR_PARAM )
			MessageBox( NULL,
						TEXT("Failed loading Configuiration file.\nFILE NOT FOUND.\n\nExiting."),
						TEXT("WOSHCESRV Failure"),
						MB_OK );
		else
			MessageBox( NULL,
						TEXT("Failed loading Configuiration file.\nUNKNOWN (syntax error?)\n\nExiting."),
						TEXT("WOSHCESRV Failure"),
						MB_OK );
		return 1;
	 }
	woshSettings->set(_FileSystem_KEY_WoshRoot, strAppDirectory, "FileSystem");
	std::string woshName = woshSettings->getValueOf( "WoshKernel", "Name", "wosh169" ).toString();

	//////////////////////////////////////////////////////////////////////////////////////
	// alloc Kernel
	WoshKernel core( woshName, woshSettings );

	//////////////////////////////////////////////////////////////////////////////////////
	// now we installed and configured all CORE modules, we can init kernel (them)
	// (so bundles will be loaded, if autoload is set)
	core.init();

	//////////////////////////////////////////////////////////////////////////////////////
	// start the kernel, just synch start bundles and set kernel to RUNNING, don't fork
	core.start();

	//////////////////////////////////////////////////////////////////////////////////////
	// install built-in blundles and apply its settings
	core.bundles().installBundle( new wosh::services::DiscoveryUdpBundle() );
	core.bundles().installBundle( new wosh::devices::WindowsMobileBundle() );

	//////////////////////////////////////////////////////////////////////////////////////
	//////////////////////////////////////////////////////////////////////////////////////
	// create the new dialog box
	// dialog is modal: when closed we get back here.. and shutdown kernel
    DialogBox(g_hInst, MAKEINTRESOURCE(IDD_MENU_DIALOG), 0,(DLGPROC)DialogProc);

	//////////////////////////////////////////////////////////////////////////////////////
	// exiting.. shutdown kernel
	core.shutdown();

	//////////////////////////////////////////////////////////////////////////////////////
	// exit
	return 0;
 }

